<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1.27/picker.js">
  <link rel="modulepreload" href="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1.27/database.js">
  <link rel="icon" href="./icon.svg">
  <meta charset="UTF-8">
  <link rel="manifest" href="./manifest.json">
  <title>emoji-picker-element</title>
  <meta name="viewport" content="width=device-width">
  <style>
    html {
      font-family: sans-serif;
    }

    body {
      margin: 0 auto;
      max-width: 1000px;
    }

    h1 {
      padding: 0 10px;
      text-align: center;
    }

    p {
      padding: 20px;
      text-align: center;
      margin: 0 auto;
    }

    .github-banner {
      position: fixed;
      top: 0;
      right: 0;
      z-index: 1000;
    }

    emoji-picker {
      margin: 0 auto;
    }

    pre {
      border: 1px solid #ededed;
      padding: 10px;
      white-space: pre-wrap;
      max-height: 300px;
      overflow-y: auto;
    }

    a, a:visited {
      color: royalblue;
    }

    .flex {
      display: flex;
      flex-direction: row;
    }

    .flex > * {
      flex: 1;
    }

    .flex > :last-child {
      margin-left: 20px;
    }

    pre {
        margin: 0;
    }

    [role="alert"] {
        display: none;
    }
    [role="alert"].shown {
        display: flex;
        flex-direction: column;
        padding: 20px;
    }
    details {
        display: flex;
        flex-direction: column;
    }

    summary {
        padding-bottom: 20px;
    }

    footer {
        display: none;
    }

    @media (max-width: 767px) {
      html {
        padding-top: 50px;
      }
      .flex {
        flex-direction: column;
      }
      .flex > :last-child {
        margin-left: 0;
      }
      h1 {
        padding: 0 50px;
      }
      p {
          padding: 10px 5px;
      }
      html {
          padding-top: 20px;
      }
      .github-banner-section {
          display: none;
      }
      footer {
          display: initial;
          text-align: center;
          padding: 20px;
      }
    }

    /* iPhone 6/7/8/X */
    @media screen and (max-width: 375px) {
      h1 {
        font-size: 1.125rem;
      }
    }

    /* iPhone 6/7/8/X */
    @media screen and (max-width: 375px) {
      emoji-picker.has-custom {
        --num-columns: 6;
        --emoji-padding: 0.25rem;
        --input-padding: 0.125rem;
      }
    }

    /* Nexus 5 */
    @media screen and (max-width: 360px) {
      emoji-picker {
        --num-columns: 6;
        --emoji-padding: 0.25rem;
        --input-padding: 0.125rem;
      }
    }

    /* JioPhone 2 */
    @media screen and (max-width: 240px) {
      emoji-picker {
        height: 80vh;
      }
    }

    @media (prefers-color-scheme: dark) {
      html {
        background: #222;
        color: #efefef;
      }
      a, a:visited {
        color: #7294f5;
      }
    }
  </style>
</head>
<body>
<section aria-label="GitHub link" class="github-banner-section">
  <a class="github-banner" href="https://github.com/nolanlawson/emoji-picker-element">
    <img width="149" height="149"
         src="https://github.blog/wp-content/uploads/2008/12/forkme_right_gray_6d6d6d.png?resize=149%2C149"
         class="attachment-full size-full" alt="Fork me on GitHub"
         data-recalc-dims="1">
  </a>
</section>
<main>
<h1>emoji-picker-element</h1>
<p>
  A lightweight emoji picker for the modern web.
</p>
<div class="flex">
  <div>
    <emoji-picker></emoji-picker>
  </div>
  <div>
    <div style="padding: 20px;">
      <div style="margin-bottom:10px;">Dark mode:</div>
      <label>
        <input type="radio" value="auto" name="darkmode" checked>
        Auto
      </label>
      <label>
        <input type="radio" value="dark" name="darkmode">
        Dark
      </label>
      <label>
        <input type="radio" value="light" name="darkmode">
        Light
      </label>
    </div>
    <div style="padding: 20px">
      <label>
        <input type="checkbox" id="custom"> Custom emoji
      </label>
    </div>
    <div  role="alert" aria-live="polite">
      <details open>
        <summary>Copied to clipboard! Details:</summary>
        <pre></pre>
      </details>
    </div>
    <div class="private-browsing-warning"
         style="padding: 20px; display: none; border: 2px dashed crimson;"
         role="alert">
      Note that <code>emoji-picker-element</code> does not support environments without IndexedDB. For polyfills
      and workarounds, see
      <a href="https://github.com/nolanlawson/emoji-picker-element/blob/master/README.md#environments-without-indexeddb">
        the README
      </a>.
    </div>
  </div>
</div>
</main>
<footer>
    <p><a href="https://github.blog/wp-content/uploads/2008/12/forkme_right_gray_6d6d6d.png?resize=149%2C149">Source code</a></p>
</footer>
<script type="module">
  import 'https://cdn.jsdelivr.net/npm/emoji-picker-element@^1.27/picker.js'
  import 'https://cdn.jsdelivr.net/npm/emoji-picker-element@^1.27/database.js' // avoid extra round-trip

  const $ = document.querySelector.bind(document)
  const $$ = _ => Array.from(document.querySelectorAll(_))
  let customEmoji

  // See https://stackoverflow.com/a/8533927
  function supportsSelector (selector) {
    const style = document.createElement('style')
    document.head.appendChild(style)
    try {
      style.sheet.insertRule(selector + '{}', 0)
    } catch (e) {
      return false
    } finally {
      document.head.removeChild(style)
    }
    return true
  }

  // check for private browsing mode to show the warning
  async function hasIDB() {
    if (typeof indexedDB === 'undefined') {
      return false
    }

    try {
      const idbFailed = await new Promise(resolve => {
        const db = indexedDB.open('test-idb')
        db.onerror = () => resolve(true)
        db.onsuccess = () => {
          indexedDB.deleteDatabase('test-idb')
          resolve(false)
        }
      })
      if (idbFailed) {
        return false
      }
    } catch (e) {
      return false
    }
    return true
  }

  async function loadCustomEmoji () {
    if (customEmoji) {
      return
    }
    const categoriesToCustomEmoji = (await (await fetch('./custom.json')).json())
    customEmoji = []
    for (const [ category, names ] of Object.entries(categoriesToCustomEmoji)) {
      for (const name of names) {
        customEmoji.push({
          category: category || undefined,
          name,
          shortcodes: [name],
          url: `./custom/${name}.svg`
        })
      }
    }
  }

  const focusVisiblePolyfillPromise = !supportsSelector(':focus-visible') &&
    import('https://cdn.jsdelivr.net/npm/focus-visible@^5/dist/focus-visible.js')

  document.addEventListener('DOMContentLoaded', async () => {
    const picker = $('emoji-picker')
    const alert = $('[role="alert"]')
    const pre = $('pre')
    const summary = $('summary')

    const copyToClipboard = async e => {
      // fun workaround for a safari bug: https://github.com/nolanlawson/emoji-picker-element/issues/281
      // use emoji-click-sync and then write the promise to the navigator.clipboard to avoid a NotAllowedError
      // normal usage is to use the emoji-click event instead
      try {
        await navigator.clipboard.write([new ClipboardItem({
          'text/plain': e.detail.then(({ unicode }) => unicode),
        })])
        summary.textContent = `Copied to clipboard! Details:`
      } catch (err) {
        console.log(err)
        summary.textContent = `Failed to write to the clipboard! Event details:`
      }
    }

    const log = async e => {
      const detail = await e.detail
      alert.classList.add('shown')
      pre.innerHTML = JSON.stringify(detail, null, 2)
    }

    picker.addEventListener('emoji-click-sync', async e => {
      await copyToClipboard(e)
      await log(e)
    })
    picker.addEventListener('skin-tone-change', async e => {
      summary.textContent = 'Skin tone changed! Details:'
      await log(e)
    })

    $$('input[name=darkmode]').forEach(input => {
      input.addEventListener('change', e => {
        picker.classList.toggle('dark', e.target.value ==='dark')
        picker.classList.toggle('light', e.target.value ==='light')
      })
    })
    $('#custom').addEventListener('change', async e => {
      if (e.target.checked) {
        await loadCustomEmoji()
        picker.customEmoji = customEmoji
      } else {
        picker.customEmoji = []
      }
      picker.classList.toggle('has-custom', !!e.target.checked)
    })

    if (!(await hasIDB())) {
      $('.private-browsing-warning').style.display = 'block';
    }

    if (focusVisiblePolyfillPromise) {
      await focusVisiblePolyfillPromise
      applyFocusVisiblePolyfill(picker.shadowRoot)
    }
  })
</script>
</body>
</html>
